package com.glsc.ngateway.oaflow.utils;

import org.apache.logging.log4j.util.Strings;

import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
//import org.json.JSONObject;


/**
 * 版权所有：国联证券信息技术管理部
 * 系统名称：股衍中证报送平台
 * 文件名称：ZipUtils.java
 * 创建时间：2020-11-20
 * 文件描述：压缩工具类
 * 文件作者：张宁
 */

public class ZipUtils {


    private static final int BUFFER_SIZE = 2 * 1024;


    // scanFiles
//    private static ArrayList<Object> scanFiles = new ArrayList<Object>();


    private static int count = 0;

    // 1、仅仅传输一个压缩文件
    public static void toZip(String sourceDir) {
        toZip(sourceDir, null, true);
    }

    // 2、目标文件 + 压缩文件位置（名字用默认）
    public static void toZip(String sourceDir, String target) {
        String fileName = new File(sourceDir).getName();
//        target = target+"/"+fileName.substring(0, fileName.lastIndexOf('.'))+".zip";
        target = target + "/" + fileName + ".zip";
        toZip(sourceDir, target, true);
    }

    //3.目标文件 + 压缩文件的位置  + 目标文件命名  + 文件夹中的文件是否在源目录
    public static void toZip(String sourceDir, String targetDir, boolean KeepDirStructure)
            throws RuntimeException {
        //Files.getDir(CstDir.config)
        File sourceFile = new File(sourceDir);
        String sourcePath = sourceFile.getParentFile().toString();
        String fileName = sourceFile.getName();
        long start = System.currentTimeMillis();
        ZipOutputStream zos = null;
        try {
            FileOutputStream out = null;
            if (Strings.isEmpty(targetDir)) {
                if (sourceFile.isDirectory()) {
                    out = new FileOutputStream(new File(sourcePath + "/" + fileName + ".zip"));
                } else {
                    out = new FileOutputStream(new File(sourcePath + "/" + fileName.substring(0, fileName.lastIndexOf('.')) + ".zip"));
                }
            } else {
                out = new FileOutputStream(new File(targetDir));

            }
            zos = new ZipOutputStream(out);
            compress(sourceFile, zos, sourceFile.getName(), KeepDirStructure);
            long end = System.currentTimeMillis();
            System.out.println("压缩完成，耗时：" + (end - start) + " ms");
        } catch (Exception e) {
            throw new RuntimeException("zip error from ZipUtils", e);
        } finally {
            if (zos != null) {
                try {
                    zos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * TODO:递归扫描指定文件夹下面的指定文件
     *
     * @return ArrayList<Object>
     * @throws FileNotFoundException
     */
    public static ArrayList<Object> scanFilesWithRecursion(String folderPath, ArrayList<Object> scanFiles) throws FileNotFoundException {
        File directory = new File(folderPath);
        if (!directory.isDirectory()) {
            throw new FileNotFoundException('"' + folderPath + '"' + " input path is not a Directory , please input the right path of the Directory. ^_^...^_^");
        }
        if (directory.isDirectory()) {
            File[] filelist = directory.listFiles();
            for (int i = 0; i < filelist.length; i++) {
                /**如果当前是文件夹，进入递归扫描文件夹**/
                if (filelist[i].isDirectory()) {
                    /**递归扫描下面的文件夹**/
                    count++;
                    scanFilesWithRecursion(filelist[i].getAbsolutePath(), scanFiles);
                } else {
                    scanFiles.add(filelist[i].getAbsolutePath());
                }
            }
        }
        return scanFiles;
    }


    /**
     * 压缩成ZIP 方法2
     *
     * @param srcFiles  需要压缩的文件列表
     * @param targetDir 压缩文件输出流
     * @throws RuntimeException 压缩失败会抛出运行时异常
     */
    //多个文件一起压缩，若上级目录为根节点，则压缩后的名字与最后一个文件的命名相同
    //若上级目录不空，则压缩后的名字为上级目录的名字
    public static void toZips(List<File> srcFiles, String targetDir) throws RuntimeException {
        long start = System.currentTimeMillis();
        FileOutputStream out = null;
        String targetName = "";
        String sourcePath = srcFiles.get(0).getParent();
        ZipOutputStream zos = null;
        try {
            if (Strings.isEmpty(targetDir)) {
                if (srcFiles.size() > 0 && srcFiles != null) {
                    targetName = srcFiles.get(srcFiles.size() - 1).getName();//获得最后一个文件的名字
                    targetName = targetName.substring(0, targetName.lastIndexOf('.'));
                }
                out = new FileOutputStream(new File(sourcePath + "/" + targetName + ".zip"));

            } else {
                out = new FileOutputStream(new File(targetDir));
            }
            zos = new ZipOutputStream(out);
            for (File srcFile : srcFiles) {
                compress(srcFile, zos, srcFile.getName(), true);
            }
            long end = System.currentTimeMillis();
            System.out.println("压缩完成，耗时：" + (end - start) + " ms");
        } catch (Exception e) {
            throw new RuntimeException("zip error from ZipUtils", e);
        } finally {
            if (zos != null) {
                try {
                    zos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static void compress(File sourceFile, ZipOutputStream zos, String name,
                                 boolean KeepDirStructure) throws Exception {
        byte[] buf = new byte[BUFFER_SIZE];
        if (sourceFile.isFile()) {
            // 向zip输出流中添加一个zip实体，构造器中name为zip实体的文件的名字
            zos.putNextEntry(new ZipEntry(name));
            // copy文件到zip输出流中
            int len;
            try(FileInputStream in = new FileInputStream(sourceFile);){
                while ((len = in.read(buf)) != -1) {
                    zos.write(buf, 0, len);
                }
                // Complete the entry
                zos.closeEntry();
                in.close();
            }
        } else {
            File[] listFiles = sourceFile.listFiles();
            if (listFiles == null || listFiles.length == 0) {
                // 需要保留原来的文件结构时,需要对空文件夹进行处理
                if (KeepDirStructure) {
                    // 空文件夹的处理
                    zos.putNextEntry(new ZipEntry(name + "/"));
                    // 没有文件，不需要文件的copy
                    zos.closeEntry();
                }
            } else {
                for (File file : listFiles) {
                    // 判断是否需要保留原来的文件结构
                    if (KeepDirStructure) {
                        // 注意：file.getName()前面需要带上父文件夹的名字加一斜杠,
                        // 不然最后压缩包中就不能保留原来的文件结构,即：所有文件都跑到压缩包根目录下了
                        compress(file, zos, name + "/" + file.getName(), KeepDirStructure);
                    } else {
                        compress(file, zos, file.getName(), KeepDirStructure);
                    }
                }
            }
        }
    }

    public static void unZip(File srcFile, String destDirPath) {
        long start = System.currentTimeMillis();
        // 判断源文件是否存在
        if (!srcFile.exists()) {
            throw new RuntimeException(srcFile.getPath() + "所指文件不存在");
        }
        // 开始解压
        ZipFile zipFile = null;
        try {
            zipFile = new ZipFile(srcFile);
            Enumeration<?> entries = zipFile.entries();
            while (entries.hasMoreElements()) {
                ZipEntry entry = (ZipEntry) entries.nextElement();
                // 如果是文件夹，就创建个文件夹
                if (entry.isDirectory()) {
                    String dirPath = destDirPath + "/" + entry.getName();
                    File dir = new File(dirPath);
                    dir.mkdirs();
                } else {
                    // 如果是文件，就先创建一个文件，然后用io流把内容copy过去
                    File targetFile = new File(destDirPath + "/" + entry.getName());
                    // 保证这个文件的父文件夹必须要存在
                    if (!targetFile.getParentFile().exists()) {
                        targetFile.getParentFile().mkdirs();
                    }
                    targetFile.createNewFile();
                    // 将压缩文件内容写入到这个文件中
                    InputStream is = zipFile.getInputStream(entry);
                    FileOutputStream fos = new FileOutputStream(targetFile);
                    int len;
                    byte[] buf = new byte[BUFFER_SIZE];
                    while ((len = is.read(buf)) != -1) {
                        fos.write(buf, 0, len);
                    }
                    // 关流顺序，先打开的后关闭
                    fos.close();
                    is.close();
                }
            }
            long end = System.currentTimeMillis();
        } catch (Exception e) {
            throw new RuntimeException("unzip error from ZipUtils", e);
        } finally {
            if (zipFile != null) {
                try {
                    zipFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 以行为单位读取文件，常用于读面向行的格式化文件
     */
    public static String readFileByLines(String fileName) {
        File file = new File(fileName);
        BufferedReader reader = null;
        StringBuffer sb = new StringBuffer();
        try {
            InputStreamReader isr = new InputStreamReader(new FileInputStream(new File(fileName)), "UTF-8");
            reader = new BufferedReader(isr);
            String tempString = null;
            int line = 1;
            // 一次读入一行，直到读入null为文件结束
            while ((tempString = reader.readLine()) != null) {
                // 显示行号
                //System.out.println("line " + line + ": " + tempString);
                sb.append(tempString);
                line++;
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                }
            }
        }
        return JsonToXmlReplaceBlank(sb.toString());

    }


    public static String JsonToXmlReplaceBlank(String xmlString) {
//        String str = DataFormatUtil.JsonToXml(jsonString);
        String dest = "";
        if (xmlString != null) {
            Pattern p = Pattern.compile("\\t|\r|\n");
            Matcher m = p.matcher(xmlString);
            dest = m.replaceAll("");
        }
        return dest;
    }

/*
    public static void read() {
        int i = 0;
        JSONObject obj = new JSONObject();
        SAXReader reader = new SAXReader();
        try {
            Document document = reader.read(new File("D://test//OTC_131101_000899_20201027_0001_R.xml"));
            Element root = document.getRootElement();
            List<Element> list = root.elements() ;
            System.out.println(list.size());
            for (Element e:list){
                i++;
                System.out.println(e.toString());
            }
        } catch (DocumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }*/

    public static void main(String args[]) {


        Map<String, String> dataMap = new HashMap<String, String>();

//        if (dataMap == null) {
//
//            System.out.println("wwwwwwwwwww");
//        } else {
//            System.out.println("datamap:" + dataMap.toString());
//        }

//        System.out.println("开始进行文件压缩");
//        toZip("D://xml//","D://");
//        System.out.println("完成文件压缩");

/*
        System.out.println("开始进行文件解压");
        unZip(new File("D://return//OTC_131101_000899_20201027_0001_R.zip"),"D://tmp");
*/
//        ResultEum re = new ResultEum.SUCCESS();


//        String result = readFileByLines("D://test//OTC_131101_000899_20201027_0001_R.xml");
//        System.out.println(JsonToXml.XmlToJson(result));
//        System.out.println(result);
//        System.out.println("完成文件解压");


    }


}
